home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus 2000 #5
/
Amiga Plus CD - 2000 - No. 5.iso
/
Tools
/
Dev
/
FPSE_src
/
cdrom.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-01-01
|
23KB
|
882 lines
/*
cdrom.c by BERO
modified by LDChen
info from psx.rules.org / doomed@c64.org
*/
#include "fpse.h"
#define RAMADDR(addr) ((void*)&ram[(addr)&0x1fffff])
#define CACHE_ENABLE 1
#define CACHE_SIZE 256
#define CACHE_PRE_READ 16
#define CACHE_SLOT_SIZE (2048+512) // easy calculation
#define INT2BCD(a) ((a/10)*16+(a%10))
#define BCD2INT(a) ((a>>4)*10+(a&0xf))
#define CON_OUTPUT 0
enum {
CdlSync, CdlNop, CdlSetloc, CdlPlay, // 00-03 ; 00-03
CdlForward, CdlBackword, CdlReadN, CdlStandby, // 04-07 ; 04-07
CdlStop, CdlPause, CdlInit, CdlMute, // 08-11 ; 08-0B
CdlDemute, CdlSetfilter, CdlSetmode, CdlGetparam, // 12-15 ; 0C-0F
CdlGetlocL, CdlGetlocP, Cdl18, CdlGetTN, // 16-19 ; 10-13
CdlGetTD, CdlSeekL, CdlSeekP, Cdl23, // 20-23 ; 14-17
Cdl24, CdlTest, CdlCheckID, CdlReadS, // 24-27 ; 18-1B
CdlReset, Cdl29, CdlReadTOC // 28-30 ; 1C-1E
};
enum {
ModeSpeed = 0x80, /* 0: normal speed 1: double speed */
ModeRT = 0x40, /* 0: ADPCM off 1: ADPCM on */
ModeSize1 = 0x20, /* 0: 2048 byte 1: 2340 byte */
ModeSize0 = 0x10, /* 0: - 1: 2328 byte */
ModeSF = 0x08, /* 0: Channel off 1: Channel on */
ModeRept = 0x04, /* 0: Report off 1: Report on */
ModeAP = 0x02, /* 0: AutoPause off 1: AutoPause on */
ModeDA = 0x01 /* 0: CD-DA off 1: CD-DA on */
};
enum {
StatPlay = 0x80, /* playing CD-DA */
StatSeek = 0x40, /* seeking */
StatRead = 0x20, /* reading data frames */
StatShellOpen = 0x10, /* once shell open */
StatSeekError = 0x04, /* seek error detected */
StatStandby = 0x02, /* spindle motor rotating */
StatError = 0x01 /* command error detected */
};
enum {
NoIntr = 0x00, /* No interrupt */
DataReady = 0x01, /* Data Ready */
Acknowledge = 0x02, /* Acknowledge */
Complete = 0x03, /* Command Complete */
DataEnd = 0x04, /* End of Data Detected */
DiskError = 0x05 /* Error Detected */
};
typedef struct {
UINT8 minute;
UINT8 second;
UINT8 frame;
UINT8 pad;
} CDLoc;
static struct {
// Registers
UINT8 stat;
UINT8 ctrl;
UINT8 mode;
UINT8 Status;
// Param
UINT8 param[8];
int paramptr;
// Result
UINT8 result[8];
int resultptr;
int resultsize;
int resultready;
// CDR Locations
CDLoc Loc;
CDLoc SeekLoc;
// Async Related
UINT8 NextStat;
UINT8 DmaReady;
UINT8 Reset;
UINT8 AsyncCause;
UINT32 NextSize;
UINT8 NextParam[8];
// Buffers
UINT8 *SectorBuf;
UINT32 SectorSize;
UINT8 LastReadInfo[8];
UINT8 file;
UINT8 chan;
UINT8 moderead;
UINT8 storedmoderead;
int retries;
} cd;
#ifdef MSB_FIRST
#define MAKEID(a,b,c,d) ( d + (c << 8) + (b << 16) + (a << 24) )
#else
#define MAKEID(a,b,c,d) ( a + (b << 8) + (c << 16) + (d << 24) )
#endif
// PSX_COUNTRY == USE_EUROPE_PSX
static UINT8 EU_Cmd25P22[8]={ 0x66,0x6F,0x72,0x20,0x55,0x2F,0x43,0x00 }; // "for U/C"
static UINT8 EU_Cmd25P23[8]={ 0x43,0x58,0x44,0x32,0x35,0x34,0x35,0x51 }; // "CXD2545Q"
static UINT8 EU_Cmd25P24[8]={ 0x43,0x58,0x44,0x32,0x35,0x34,0x35,0x51 }; // "CXD2545Q"
static UINT8 EU_Cmd25P25[8]={ 0x43,0x58,0x44,0x31,0x38,0x31,0x35,0x51 }; // "CXD1815Q"
static UINT8 EU_SCEx[6] = { 0x09, 0xA9, 0x3D, 0x2B, 0xA5, 0x74 }; // SCEE European
static UINT32 EU_SCExID = MAKEID('S','C','E','E');
// PSX_COUNTRY == USE_AMERICAN_PSX
static UINT8 US_Cmd25P22[8]={ 0x66,0x6F,0x72,0x20,0x55,0x53,0x2F,0x41 }; // "for US/A"
static UINT8 US_Cmd25P23[8]={ 0x43,0x58,0x44,0x31,0x37,0x38,0x32,0x42 }; // "CXD1782B"
static UINT8 US_Cmd25P24[8]={ 0x43,0x58,0x44,0x32,0x35,0x31,0x36,0x51 }; // "CXD2516Q"
static UINT8 US_Cmd25P25[8]={ 0x43,0x58,0x44,0x31,0x31,0x39,0x39,0x42 }; // "CXD1199B"
static UINT8 US_SCEx[6] = { 0x09, 0xA9, 0x3D, 0x2B, 0xA5, 0xF4 }; // SCEA U.S.
static UINT32 US_SCExID = MAKEID('S','C','E','A');
// PSX_COUNTRY == USE_JAPAN_PSX
static UINT8 JP_Cmd25P22[8]={ 0x66,0x6F,0x72,0x20,0x4A,0x61,0x70,0x61 }; // "for Japa"
static UINT8 JP_Cmd25P23[8]={ 0x43,0x58,0x44,0x32,0x35,0x34,0x35,0x51 }; // "CXD2545Q"
static UINT8 JP_Cmd25P24[8]={ 0x43,0x58,0x44,0x32,0x35,0x34,0x35,0x51 }; // "CXD2545Q"
static UINT8 JP_Cmd25P25[8]={ 0x43,0x58,0x44,0x31,0x38,0x31,0x35,0x51 }; // "CXD1815Q"
static UINT8 JP_SCEx[6] = { 0x09, 0xA9, 0x3D, 0x2B, 0xA5, 0x74 }; // SCEI Japanese
static UINT32 JP_SCExID = MAKEID('S','C','E','I');
static UINT8 Cmd25P22[8];
static UINT8 Cmd25P23[8];
static UINT8 Cmd25P24[8];
static UINT8 Cmd25P25[8];
static UINT8 SCEx[6];
static UINT32 SCExID;
#if CACHE_ENABLE==0
static UINT8 SectorBuf[CACHE_SLOT_SIZE];
#else
static UINT8 SectorBuf[CACHE_SLOT_SIZE*CACHE_SIZE];
static CDLoc CacheAddress[CACHE_SIZE];
static int CacheIdx = 0;
static void init_cd_cache(void)
{
memset(CacheAddress,0,CACHE_SIZE*sizeof(CDLoc));
}
static UINT8 *get_cd_cache(CDLoc *loc)
{
int x;
UINT8 *sect,*ret;
CDLoc l;
// Search in the cache
for (x=0; x<CACHE_SIZE; x++)
if (*(UINT32 *)loc == *(UINT32 *)(CacheAddress+x))
return &SectorBuf[x*CACHE_SLOT_SIZE];
// Save position for return
ret = &SectorBuf[CacheIdx*CACHE_SLOT_SIZE];
l = *loc;
// Read 'CACHE_PRE_READ' sectors per time instead of one (more speed)
for (x=0; x<CACHE_PRE_READ; x++)
{
CacheAddress[CacheIdx] = l; // Set active address
sect = CD_Read((UINT8 *)&l); // read the sector
CD_Wait(); // wait end-of-read
memcpy(&SectorBuf[CacheIdx*CACHE_SLOT_SIZE],
sect,2352); // copy sector in cache
if (++l.frame >= 75) // Advance CD pointer
{
l.frame = 0;
if (++l.second >= 60)
{
l.second=0;
l.minute++;
}
}
if (++CacheIdx >= CACHE_SIZE) CacheIdx = 0; // Go to next slot
}
return ret;
}
#endif
#define EVENT_SETUP(n,irq,s) VSync_Register |= 0x80000000 | (1<<INT_CD); \
Event_List[INT_CD] = n; \
cd.NextStat = irq; cd.NextSize = s
/*
result[0]
0x80 CD-DA Play
0x02 working?
*/
static int get_sector_size()
{
switch( cd.mode & 0x30 ) {
case 0x00: return 2048;
case 0x10: return 2328;
case 0x20: return 2352;
}
return 2352;
}
static int UpdateSeekPosition()
{
/*
if ((cd.mode & ModeRept) &&
(cd.Status & StatPlay))
{
CD_GetSeek((UINT8*)&cd.SeekLoc);
return 1;
}
*/
if (++cd.SeekLoc.frame >= 75)
{
cd.SeekLoc.frame = 0;
if (++cd.SeekLoc.second >= 60)
{
cd.SeekLoc.second=0;
cd.SeekLoc.minute++;
}
}
return 0;
}
#if CON_OUTPUT
static int cnt = 0;
#endif
static int cdrom_async()
{
#if CON_OUTPUT
printf("ASync=%d - ctrl=%x\n",cd.AsyncCause,cd.ctrl);
#endif
/*
if (cd.ctrl & 0x40)
{
if (cnt<10)
{
PRINTF("Forward CDIRQ\n");
cnt++;
VSync_Register |= 0x80000000 | (1<<INT_CD);
Event_List[INT_CD] = 100;
return;
}
cnt = 0;
cd.ctrl &= ~0x40;
}
*/
if (hwarea[0x1070] && (1<<INT_CD)) // cd.stat == 1)
{
if (cd.retries<10)
{
//if (cd.NextStat != 3) {
#if CON_OUTPUT
PRINTF("%3d) Forward CDIRQ\n",cnt);
cnt++;
#endif
//}
cd.retries++;
VSync_Register |= 0x80000000 | (1<<INT_CD);
Event_List[INT_CD] = 50;
return 0;
}
}
cd.retries = 0;
//cnt = 0;
#if CON_OUTPUT
printf("Setup CDIRQ %d\n",cd.NextStat);
#endif
if (CD_Wait() != FPSE_OK)
{
#if CON_OUTPUT
printf("CDIRQ error detected\n");
#endif
cd.NextParam[0] |= StatError;
cd.NextStat = DiskError;
cd.NextSize = 1;
cd.DmaReady = 0;
}
cd.stat = cd.NextStat;
cd.resultsize = cd.NextSize;
cd.resultptr = 0;
cd.resultready = 1;
cd.ctrl &= ~(0x80|0x40);
cd.ctrl |= cd.DmaReady;
cd.DmaReady = 0;
memcpy(cd.result,cd.NextParam,8);
if (cd.stat == DiskError) return 1;
switch (cd.AsyncCause) {
case 1: // Read
#if CACHE_ENABLE==1
if (cdusecache) cd.SectorBuf = get_cd_cache(&cd.SeekLoc);
else
#endif
cd.SectorBuf = CD_Read((UINT8 *)&cd.SeekLoc);
cd.SectorSize = get_sector_size();
cd.NextParam[0] = cd.Status;
cd.AsyncCause = 5;
cd.DmaReady = 0x40;
EVENT_SETUP(100,1,1);
break;
case 2: // Pause
cd.AsyncCause = 0;
cd.NextParam[0] = cd.Status;
cd.ctrl |= 0x80; // (cd.ctrl | 0x80) & ~0x40;
EVENT_SETUP(100,2,1);
break;
case 3: // Play
cd.SectorSize = get_sector_size();
cd.AsyncCause = 4;
cd.NextParam[0] = 0;
UpdateSeekPosition();
EVENT_SETUP(400,3,1);
break;
case 4:
cd.AsyncCause = 3;
cd.NextParam[0] = cd.Status;
if (cd.mode & ModeRept)
{
cd.NextParam[1] = 1;
cd.NextParam[2] = 0x80;
cd.NextParam[3] = INT2BCD(cd.SeekLoc.minute);
cd.NextParam[4] = INT2BCD(cd.SeekLoc.second) | 0x80;
cd.NextParam[5] = INT2BCD(cd.SeekLoc.frame);
EVENT_SETUP(400,1,8);
} else EVENT_SETUP(400,1,1);
break;
case 5:
if (cd.SectorBuf != NULL) {
memcpy(SectorBuf,cd.SectorBuf,2352);
memcpy(cd.LastReadInfo,cd.SectorBuf,8);
}
cd.SectorBuf = SectorBuf;
UpdateSeekPosition();
switch ((cd.moderead = cd.storedmoderead)) {
case 0:
cd.SectorBuf += 12; break;
}
cd.AsyncCause = 1;
cd.NextParam[0] = cd.Status | StatRead;
EVENT_SETUP(100,3,1);
break;
case 6: // CdlSync
cd.AsyncCause = 2;
cd.NextParam[0] = cd.Status;
cd.ctrl |= 0x80;
EVENT_SETUP(100,4,1);
break;
case 7: // ReadS
#if CACHE_ENABLE==1
if (cdusecache) cd.SectorBuf = get_cd_cache(&cd.SeekLoc);
else
#endif
cd.SectorBuf = CD_Read((UINT8 *)&cd.SeekLoc);
cd.SectorSize = get_sector_size();
cd.NextParam[0] = cd.Status;
cd.AsyncCause = 8;
cd.DmaReady = 0x40;
EVENT_SETUP(140,1,1);
break;
case 8:
if (cd.SectorBuf != NULL) {
memcpy(SectorBuf,cd.SectorBuf,2352);
memcpy(cd.LastReadInfo,cd.SectorBuf,8);
}
cd.SectorBuf = SectorBuf;
UpdateSeekPosition();
switch ((cd.moderead = cd.storedmoderead)) {
case 0:
cd.SectorBuf += 12; break;
}
cd.AsyncCause = 7;
cd.NextParam[0] = cd.Status | StatRead;
EVENT_SETUP(25,3,1);
break;
default:
cd.AsyncCause = 0;
break;
}
return 1;
}
void cd_initvar()
{
memset(&cd,0,sizeof(cd));
VSyncCallBack[INT_CD] = cdrom_async;
#if CACHE_ENABLE==1
init_cd_cache();
#endif
switch (psx_country)
{
case USE_AMERICAN_PSX:
memcpy(Cmd25P22,US_Cmd25P22,sizeof(Cmd25P22));
memcpy(Cmd25P23,US_Cmd25P23,sizeof(Cmd25P23));
memcpy(Cmd25P24,US_Cmd25P24,sizeof(Cmd25P24));
memcpy(Cmd25P25,US_Cmd25P25,sizeof(Cmd25P25));
memcpy(SCEx,US_SCEx,sizeof(SCEx));
SCExID = US_SCExID;
printf("SCEA zone selected.\n");
break;
case USE_EUROPE_PSX:
memcpy(Cmd25P22,EU_Cmd25P22,sizeof(Cmd25P22));
memcpy(Cmd25P23,EU_Cmd25P23,sizeof(Cmd25P23));
memcpy(Cmd25P24,EU_Cmd25P24,sizeof(Cmd25P24));
memcpy(Cmd25P25,EU_Cmd25P25,sizeof(Cmd25P25));
memcpy(SCEx,EU_SCEx,sizeof(SCEx));
SCExID = EU_SCExID;
printf("SCEE zone selected.\n");
break;
case USE_JAPAN_PSX:
memcpy(Cmd25P22,JP_Cmd25P22,sizeof(Cmd25P22));
memcpy(Cmd25P23,JP_Cmd25P23,sizeof(Cmd25P23));
memcpy(Cmd25P24,JP_Cmd25P24,sizeof(Cmd25P24));
memcpy(Cmd25P25,JP_Cmd25P25,sizeof(Cmd25P25));
memcpy(SCEx,JP_SCEx,sizeof(SCEx));
SCExID = JP_SCExID;
printf("SCEI zone selected.\n");
break;
}
}
int cd0_read(void)
{
int ret = cd.ctrl;
if (cd.resultsize && cd.resultready) ret|=0x20; else ret&=~0x20;
// printf("read cd0 %x\n",ret|0x18);
return ret|0x18;
}
int cd1_read(void)
{
int ret=0;
if (cd.resultsize) {
ret = cd.result[cd.resultptr++];
if (cd.resultptr>=cd.resultsize) {
cd.resultptr = cd.resultsize = 0;
cd.resultready = 0;
}
}
// printf("read cd1 %x\n",ret);
return ret;
}
int cd2_read(void)
{
// printf("read cd2 ,0\n");
return 0;
}
int cd3_read(void)
{
// printf("read cd3 %x\n",cd.stat);
return cd.stat;
}
#define RESULT(n) cd.result[0] = n; cd.resultsize = 1
#define SRESULT cd.result[0] = cd.Status; cd.resultsize = 1
void cd0_write(int data)
{
/* write 0??
write read & 3?
*/
// printf("write cd0 %x\n",data);
// cd.ctrl = data;
if (data==0) {
cd.paramptr = 0;
cd.resultready = 0;
}
if (data&1) cd.resultready = 1;
if (data==1) cd.Reset = 1;
}
void cd2_write(int data)
{
// printf("write cd2 %x\n",data);
if (cd.Reset==2 && data==7) {
cd.paramptr = 0;
cd.resultready = 1;
cd.Reset = 0;
cd.stat = 0;
cd.ctrl = cd.ctrl & ~3; // 0;
return;
}
cd.Reset = 0;
if (cd.paramptr<8)
cd.param[cd.paramptr++] = data;
}
void cd3_write(int data)
{
// cd.stat = data;
// printf("write cd3 %x\n",data);
if (data==7 && cd.Reset==1) cd.Reset=2;
else cd.Reset=0;
if (cd.resultready && data==7) {
cd.resultsize = cd.resultptr = 0;
cd.stat = 0;
}
}
#if CON_OUTPUT
#define PRINTRESULT \
printf(" Resultsize=%2d - %02x %02x %02x %02x %02x %02x %02x %02x\n", \
cd.resultsize, \
cd.result[0], cd.result[1], cd.result[2], cd.result[3], \
cd.result[4], cd.result[5], cd.result[6], cd.result[7]);
#else
#define PRINTRESULT
#endif
void cd1_write(int data)
{
static char *cmdname[]= {
"CdlSync", "CdlNop", "CdlSetloc", "CdlPlay",
"CdlForward", "CdlBackword", "CdlReadN", "CdlStandby",
"CdlStop", "CdlPause", "CdlReset", "CdlMute",
"CdlDemute", "CdlSetfilter", "CdlSetmode", "CdlGetparam",
"CdlGetlocL", "CdlGetlocP", "Cdl18", "CdlGetTN",
"CdlGetTD", "CdlSeekL", "CdlSeekP", "Cdl23",
"Cdl24", "CdlTest", "CdlCheckID", "CdlReadS"
};
if (data<28) {
PRINTF("%s\n",cmdname[data]);
}
#if CON_OUTPUT
printf("Command %x - Code %02x %02x %02x %02x %02x %02x %02x %02x\n",
data,
cd.param[0], cd.param[1], cd.param[2], cd.param[3],
cd.param[4], cd.param[5], cd.param[6], cd.param[7]);
#endif
cd.stat = 2;
switch(data){
case CdlSync:
cd.NextParam[0] = cd.Status;
cd.AsyncCause = 6;
EVENT_SETUP(100,3,1);
cd.ctrl |= 0x80;
cd.stat = 3;
PRINTRESULT
return;
case CdlNop:
cd.stat = 3;
SRESULT;
break;
case CdlSetloc:
if (!(cd.param[0] | cd.param[1] | cd.param[2]))
{
cd.Loc = cd.SeekLoc;
} else {
cd.Loc.minute = BCD2INT(cd.param[0]);
cd.Loc.second = BCD2INT(cd.param[1]);
cd.Loc.frame = BCD2INT(cd.param[2]);
}
cd.Status |= StatStandby;
cd.NextParam[0] = cd.Status;
cd.AsyncCause = 0;
EVENT_SETUP(100,3,1);
cd.ctrl |= 0x80;
PRINTRESULT
return;
/*
SRESULT;
break;
*/
case CdlPlay:
CD_Play((UINT8 *)&cd.SeekLoc);
cd.Status |= (StatPlay | StatStandby);
cd.NextParam[0] = cd.Status;
cd.AsyncCause = 4;
EVENT_SETUP(400,3,1);
cd.DmaReady = 0x40;
cd.ctrl |= 0x80;
PRINTRESULT
return;
case CdlForward:
case CdlBackword:
cd.stat = 2;
SRESULT;
break;
case CdlReadS:
cd.AsyncCause = 7;
goto ContinueRead;
case CdlReadN:
cd.AsyncCause = 1;
ContinueRead:
cd.Status |= StatStandby;
if (memcmp(&cd.SeekLoc,&cd.Loc,sizeof(CDLoc)))
cd.SeekLoc = cd.Loc;
cd.NextParam[0] = cd.Status;
EVENT_SETUP(100,3,1);
// cd.SectorBuf = cd_read((UINT8 *)&cd.SeekLoc);
// cd.SectorSize = get_sector_size();
cd.ctrl |= 0x80;
PRINTRESULT
return;
case CdlInit:
cd.mode = 0;
case CdlReset:
case CdlStandby:
cd.stat = 2;
cd.Status = (cd.Status & ~StatPlay) | StatStandby;
SRESULT;
break;
case CdlStop:
cd.stat = 2;
if (cd.Status & StatPlay)
CD_Stop();
cd.Status &= ~(StatPlay | StatStandby);
SRESULT;
break;
case CdlPause:
// if (++cnt>=17) FPSE_Flags |= VERBOSE | DISASMFLG;
if (cd.Status & StatPlay) CD_Stop();
cd.Status = (cd.Status & ~StatPlay) | StatStandby;
cd.AsyncCause = 2;
cd.NextParam[0] = cd.Status;
// cd.stat = 4;
EVENT_SETUP(10,4,1); // 4,2,1);
cd.DmaReady = 0x40;
cd.ctrl |= 0x80; // (cd.ctrl | 0x80) & ~0x40;
PRINTRESULT
return;
case CdlMute:
case CdlDemute:
cd.stat = 2;
SRESULT;
break;
case CdlSetfilter:
cd.stat = 2;
cd.file = cd.param[0];
cd.chan = cd.param[1];
SRESULT;
break;
case CdlSetmode:
cd.mode = cd.param[0];
cd.storedmoderead = (cd.mode & 0x30) >> 4;
cd.Status |= StatStandby;
cd.NextParam[0] = cd.Status;
cd.AsyncCause = 0;
EVENT_SETUP(100,3,1);
cd.ctrl |= 0x80;
PRINTRESULT
return;
SRESULT;
break;
case CdlGetparam:
cd.stat = 2;
cd.result[0] = cd.Status; /* status */
cd.result[1] = cd.mode;
cd.result[2] = cd.file; /* file */
cd.result[3] = cd.chan; /* channel */
cd.result[4] = 0;
cd.result[5] = 0;
cd.resultsize = 6;
break;
case CdlGetlocL:
cd.stat = 2;
/*
cd.result[0] = INT2BCD(cd.SeekLoc.minute); // min
cd.result[1] = INT2BCD(cd.SeekLoc.second); // sec
cd.result[2] = INT2BCD(cd.SeekLoc.frame); // frame
cd.result[3] = cd.mode; // mode
cd.result[4] = cd.file; // file
cd.result[5] = cd.chan; // channel
cd.resultsize = 6;
*/
memcpy(cd.result,cd.LastReadInfo,8);
cd.resultsize = 8;
break;
case CdlGetlocP:
cd.stat = 2;
cd.result[0] = 1; /* track */
cd.result[1] = 0; /* index */
cd.result[2] = cd.LastReadInfo[0]; /* min */
cd.result[3] = cd.LastReadInfo[1]; /* sec */
cd.result[4] = cd.LastReadInfo[2]; /* frame */
cd.result[5] = cd.LastReadInfo[0]; /* Amin */
cd.result[6] = cd.LastReadInfo[1]; /* Asec */
cd.result[7] = cd.LastReadInfo[2]; /* Aframe */
cd.resultsize = 8;
break;
case CdlGetTN:
cd.stat = 2;
CD_GetTN(cd.result);
cd.result[0] = cd.Status; /* status */
cd.result[1] = INT2BCD(cd.result[1]); /* first track */
cd.result[2] = INT2BCD(cd.result[2]); /* total track */
cd.resultsize = 3;
break;
case CdlGetTD:
cd.stat = 2;
CD_GetTD(cd.result,cd.param[0]);
cd.result[0] = cd.Status; /* status */
cd.result[1] = INT2BCD(cd.result[1]); /* min */
cd.result[2] = INT2BCD(cd.result[2]); /* sec */
cd.resultsize = 3;
break;
case CdlSeekL:
case CdlSeekP:
cd.SeekLoc = cd.Loc;
#if CON_OUTPUT
printf("%02x:%02x:%02x\n",
cd.SeekLoc.minute,cd.SeekLoc.second,cd.SeekLoc.frame);
#endif
cd.Status |= StatStandby;
cd.NextParam[0] = cd.Status;
cd.AsyncCause = 0;
EVENT_SETUP(100,2,1);
cd.ctrl |= 0x80;
PRINTRESULT
return;
cd.Status |= StatStandby;
SRESULT;
break;
case CdlTest:
cd.Status |= StatStandby;
switch (cd.param[0]) {
case 0x20:
cd.result[0] = 0x94; // BIOS Timestamps
cd.result[1] = 0x09;
cd.result[2] = 0x19;
cd.result[3] = 0xC0;
break;
case 0x22:
memcpy(cd.result,Cmd25P22,8);
break;
case 0x23:
memcpy(cd.result,Cmd25P23,8);
break;
case 0x24:
memcpy(cd.result,Cmd25P24,8);
break;
case 0x25:
memcpy(cd.result,Cmd25P25,8);
break;
}
cd.resultsize = 8;
cd.stat = 3;
break;
case CdlCheckID:
cd.result[0] = 0x08; // 0x10=Audio CD 0x08=Data Tracks
// 0x00=Don't Known
cd.result[1] = 0x00; // 0x80=Copied CD else Original
cd.result[2] = 0x00;
cd.result[3] = 0;
*(UINT32 *)(cd.result + 4) = SCExID;
cd.resultsize = 8;
cd.stat = 2;
break;
/*
case CdlReadS:
cd.Status |= StatStandby;
SRESULT;
cd.stat = 2;
break;
*/
default:
printf("unknown cd command %d - %xh\n",data,data);
cd.stat = 2;
}
PRINTRESULT
// VSync_Register = 0;
cd.resultptr = 0;
cd.resultready = 1;
/* cd_interrupt happen */
Irq_Pulse |= (1<<INT_CD);
}
void dma3_exec(UINT32 adr,UINT32 bcr,UINT32 chcr)
{
int size;
#if CON_OUTPUT
printf("cdma called: %08x %08x %08x\n",(int)adr,(int)bcr,(int)chcr);
#endif
// get the size in bytes
size = (bcr>>16)*(bcr&0xffff)*4;
if (!size) size = bcr*4;
CompileFlush(adr,adr+size);
// check the dma_chcr
switch(chcr) {
case 0x11000000:
if (cd.SectorBuf != NULL)
{
switch (cd.moderead) {
case 2:
memcpy(RAMADDR(adr),SectorBuf,size);
cd.SectorSize = 2048;
cd.SectorBuf += 12;
cd.moderead = 0;
break;
case 1:
case 0:
memcpy(RAMADDR(adr),cd.SectorBuf,size);
cd.SectorBuf += size;
if ((cd.SectorSize-=size) <= 0)
cd.ctrl &= ~0x40;
break;
}
/*
if (size <= 12) memcpy(RAMADDR(adr),cd.SectorBuf,size);
else {
memcpy(RAMADDR(adr),SectorBuf+12,size);
cd.ctrl &= ~0x40;
}
*/
} else {
memset(RAMADDR(adr),0,size);
cd.ctrl &= ~0x40;
}
break;
}
}